package webapp

import (
	"gitee.com/captials-team/ubdframe/src/apps"
	"gitee.com/captials-team/ubdframe/src/common/utils"
	"gitee.com/captials-team/ubdframe/src/domain/configstc"
	"gitee.com/captials-team/ubdframe/src/pkg/gin_http"
	v1log "gitee.com/captials-team/ubdframe/src/pkg/logs"
	"gitee.com/captials-team/ubdframe/src/pkg/proxyhandler"
	httplibs "gitee.com/captials-team/ubdframe/src/pkg/viewhandler"
	"github.com/gin-contrib/static"
	"github.com/gin-gonic/gin"
	"go.uber.org/dig"
	"html/template"
	"net/http"
)

type ApiServer struct {
	*apps.ApiServer
	di   *dig.Container
	conf *configstc.WebAppConfig
	l    v1log.ILog

	gin_http.CorsOption

	funcMaps []template.FuncMap

	templateParamFunc func(*http.Request) string
}

func (s *ApiServer) Name() string {
	return "web_server"
}

func (s *ApiServer) InitRouter() {
	s.Engine().GET("ping", gin_http.PingHandler)
	s.regRouter(s.Engine())
}

func (s *ApiServer) InitRouterForGin(engine *gin.Engine) {
	s.regRouter(engine)
}

// regRouter 注册路由
func (s *ApiServer) regRouter(engine *gin.Engine) {
	//默认增加跨域
	//已通过 ApiServer.WithCors() 跨域
	//if !s.NoCors {
	//	corsConfig := cors.DefaultConfig()
	//	corsConfig.AllowOrigins = []string{"*"}
	//	corsConfig.AllowHeaders = []string{"*"}
	//	corsConfig.OptionsResponseStatusCode = http.StatusOK
	//	engine.Use(cors.New(corsConfig))
	//}

	//proxy和staticServe不可使用engine.Group功能
	s._regProxyRouter(engine)
	s._regStaticRouter(engine)
	s._regTemplateEngine(engine)

	return
}

// _regStaticRouter 静态文件支持
func (s *ApiServer) _regStaticRouter(engine *gin.Engine) {
	prefix := "/"
	if s.conf.RoutePrefix != "" {
		prefix = s.conf.RoutePrefix
	}
	prefix = utils.KeepHasPrefix(prefix, "/")
	if s.conf.StaticRouter != "" {
		prefix = s.conf.StaticRouter
	} else {
		prefix = prefix + "/static"
	}
	//静态文件
	//访问地址： http://{DOMAIN}/{prefix}

	path := s.conf.StaticPath
	if path == "" {
		s.l.Warn("[Web Static] No Configured %s", path)
		return
	}
	if !utils.FilePathExist(path) {
		panic("[Web Static] Dir Not Exist " + path)
	}
	engine.Use(static.ServeRoot(prefix, path))
	s.l.Info("[Web Static] %s\t\t--> %s", prefix, path)

	return
}

// _regProxyRouter 转发路由
func (s *ApiServer) _regProxyRouter(engine *gin.Engine) {
	//转发Proxy功能
	engine.Use(proxyhandler.ProxyHandler(proxyhandler.NewProxyGroup(s.conf.ProxyRules...)...))
	return
}

// _regTemplateEngine 模板引擎支持
func (s *ApiServer) _regTemplateEngine(engine *gin.Engine) {
	prefix := "/"
	tplPath := s.conf.TemplatePath

	if s.conf.RoutePrefix != "" {
		prefix = s.conf.RoutePrefix
	}

	prefix = utils.KeepHasPrefix(prefix, "/")
	if s.conf.TemplateRouter != "" {
		prefix = s.conf.TemplateRouter
	} else {
		prefix = prefix + "/views"
	}

	//目录存在才配置
	path := s.conf.TemplatePath
	if path == "" || !utils.FilePathExist(path) {
		s.l.Warn("[Web Template] Not Configure %s", path)
		return
	}
	//自定义设置渲染器
	viewConfig := httplibs.DefaultViewHandlerConfig
	//viewConfig.ViewFs = viewFs
	viewConfig.ViewDir = tplPath
	viewConfig.FuncMaps = s.funcMaps

	viewConfig.ParamFunc = s.templateParamFunc
	//可指定ParamFunc
	// 示例：可从get参数 r 来指定模板解析名称，此时访问地址应为：  xxx/views?r=index.html
	//viewConfig.ParamFunc = func(r *http.Request) string {
	//	err := r.ParseForm()
	//	s.l.Ctl(err != nil).Error("ParseForm %s", err)
	//	return r.FormValue("r")
	//}

	viewHandler := httplibs.NewViewHandler(viewConfig)
	viewHandler.AddLogger(s.l)
	viewHandler.InitiateRender()
	viewHandler.GinRouterJump(engine, prefix)
	s.l.Info("[Web Template] %s\t\t--> %s", prefix, path)
	return
}

func (s *ApiServer) AddFuncMap(funcs ...template.FuncMap) {
	s.funcMaps = append(s.funcMaps, funcs...)
}

func (s *ApiServer) SetTemplateParseFunc(f func(r *http.Request) string) {
	s.templateParamFunc = f
}

func (s *ApiServer) Start() error {
	if !s.Module() {
		s.InitRouter()
	}
	return s.ApiServer.Start()
}

func (s *ApiServer) Stop() error {
	return s.ApiServer.Stop()
}

func NewApiServer(di *dig.Container, conf *configstc.WebAppConfig, logger v1log.ILog) *ApiServer {
	s := &ApiServer{
		di:        di,
		conf:      conf,
		l:         logger,
		ApiServer: apps.NewApiServer(gin.Default(), conf.WebServer),
	}

	s.WithName(conf.Name)
	s.WithCors() //开启跨域设置

	return s
}
